Great observation!
It’s a bit more subtle than a bug. While Categorical.log_prob returns a gradient with sum zero would leave you in the realm of probability measures when infinitesimally moving in that direction, NLLLoss's backward has a constant offset that will happily catapult you outside the admissible input space.
In math lingo, Categorical.log_prob computes the gradient on the (not quite but locally if no probs are zero) manifold of probability vectors, which lies in the tangent space of that “manifold” while NLLLoss computes the gradient on the larger parameter space of the formula given in the documentation. The difference is orthogonal to the tangent space of probabilities.
The effect will go away if you force the input to NLLLoss to lie in the log-of-probability-measures manifold, i.e. change the line to
    loss = torch.nn.NLLLoss()( inp.log().log_softmax(1), action )

Then the log_softmax does not change your input (it is a projection on log probability measures, so the identity on them) but its backward will do the projection on the tangent space (if you liked the math: because the normal component is in the kernel of the Jacobian) and you’ll get gradients for inp that  might better match your expectation.
Best regards
Thomas