I think the problematic part trying to get rid of the loops would be the batched way of creating the range indexing for batches.
Probably creating the linear indices beforehand and index the result tensor directly would work.
However, how performance critical is this code?
E.g. if you just run it once in your script, I wouldn’t invest a lot of time improving its performance, but focus on other parts of the code.