You need to make the hook a closure - just redefine it at every step, and use the data in its body:
optimizer.zero_grad()

output = model(data)
def hook(d_output):
    return d_output * data.mean() # you can use the data here
output.register_hook(hook)

loss = criterion(output, target)
loss.backward()
optimizer.step()