Sometimes I do it this way:
Block[{NIntegrate, x, y, z}, intfunc[z_] = NIntegrate[integrand, {x, -5, 5}, {y, -10, 1000}]; ]; intfunc[7.] (* 3.5009*10^7 *)
It's not a great general programmatic way to go, but in the middle of solving a problem, in which I have constructed an expression integrand, this is to me an easy way. Blocking x, y, and z should be unnecessary (or else integrand could not depend on them), but sometimes I'm over-cautious.
Update: Explanation
The problem has three aspects: (1) to get the code for integrand to evaluate (2) before the pattern named z is evaluated (3) without NIntegrate evaluating, all during the evaluation of Set or SetDelayed. I'll say something about the optional ?NumericQ at the end.
There are various ways to address this. One way is to go around the problem entirely and use functions that have all parameters as arguments. This is a better way to write a program. This is the workaround the OP points out in the question (and repeated by Bob Hanlon).
But there are ways to address the problem directly. Block, as in
Block[{NIntegrate}, code]
blocks the evaluation of NIntegrate during the execution of code. Basically, the symbol is temporarily cleared of all its values and attributes. So when the code
intfunc[z_] = NIntegrate[integrand, {x, -5, 5}, {y, -10, 1000}];
is evaluated, all the arguments of NIntegrate are evaluated, and the definition becomes
intfunc[z_] = NIntegrate[<fn expr in x,y,z>, {x, -5, 5}, {y, -10, 1000}];
where <fn expr in x,y,z> represents the value of integrand; and that is what intfunc[z_] is set to be equal to.
Another solution is substitution, which I skipped because I thought someone had already suggested it; e.g.,
intfunc[z0_] := NIntegrate[integrand /. z -> z0, {x, -5, 5}, {y, -10, 1000}];
The overhead from ?NumericQ is negligible. It could be quite desirable to use intfunc[z0_?NumericQ]... in the definitions above, especially if intfunc[z] is to be passed to another solver.
Why doesn't this work, with or without NumericQ?
intfunc[z_] := NIntegrate[integrand, {x, -5, 5}, {y, -10, 1000}];
Inspecting the DownValues of intfunc will help the explanation:
DownValues[intfunc] (* {HoldPattern[intfunc[z_]] :> NIntegrate[integrand, {x, -5, 5}, {y, -10, 1000}]} *)
SetDelayed created a rewrite rule that replaces all instances of the symbol z in the literal, unevaluated expression NIntegrate[integrand, {x, -5, 5}, {y, -10, 1000}] by the argument to intfunc. There are no instances of z in that code. So both of these calls,
intfunc[7.] intfunc[10.]
result in the same thing
NIntegrate[integrand, {x, -5, 5}, {y, -10, 1000}]
which is then evaluated. At this point integrand is evaluated by NIntegrate and the symbolic z shows up. In @march's suggestion
intfunc[z0_] := Block[{z = z0}, NIntegrate[ ... ]]
the value of z would be equal to the value of the argument z0; if numeric, the evaluation of NIntegrate would proceed with no other difficulties except those posed by a pesky integrand.
As a final remark, the OP's actual expression for integrand is certainly pesky. IMO the integrand itself is the only reason that NIntegrate is slow.
intfunc[z0_] := Block[{z = z0}, NIntegrate[ ... ]]$\endgroup$