it is best to have multiplicands in a single memory block (buffer), but this is often impossible to arrange, as copying is not efficient, and “out” argument breaks gradients. if you mean matrix multiplication, you can’t “pack” tensors with varying shapes either.
apart from that, you can only reduce invocation overhead a bit (e.g. with JIT), but this will likely be insignificant, unless you’re dealing with hundreds of small tensors.