For anyone who needs a workaround in the meantime (I got here from googling), I have implemented and regularly use these hacks:
def batch_apply(fn, *inputs):
    return torch.stack([fn(*(a[0] for a in args)) for args in zip(*(inp.split(1) for inp in inputs))])

# Specific versions for readability:
def batch_apply1(fn, inp1):
    return torch.stack([fn(i[0]) for i in inp1.split(1)])

def batch_apply2(fn, inp1, inp2):
    return torch.stack([fn(i1[0], i2[0]) for (i1, i2) in zip(inp1.split(1), inp2.split(1))])

And use them like this:
v = Variable(torch.randn(3, 5))
t = Variable(torch.randn(3, 5, 5))
batch_apply(lambda v, t: torch.potrs(v, t)[:,0], v, t)  # Variable containing ... [torch.FloatTensor of size (3,5)]
batch_apply(lambda v: torch.diag(v), v)  # Variable containing ... [torch.FloatTensor of size (3,5,5)]