You could assign the precomputed gradients to the .grad attribute of all parameters and call optimizer.step() afterwards.  Here is a small example:
lin = nn.Linear(1, 1, bias=False)
optimizer = torch.optim.SGD(lin.parameters(), lr=1e-3)

print(lin.weight)
lin.weight.grad = torch.ones_like(lin.weight) * 10
print(lin.weight.grad)
optimizer.step()
print(lin.weight)