Gradient passthough in PyTorch
Thank you @thanatoz for answering that in the comments.  In fact, this did solve my problem.  I also realized from other people's VQVAE code, there is also another possible solution in which the retrain_graph parameter is not needed.  My example code could be written ...
x = self.linear1(x)        
min, max = int(x.min()), int(x.max())        
bins = torch.linspace(min, max+1, 16)
x_buckets = torch.bucketize(x.detach(), bins) # forced to detach here
x = x + (x - x_buckets).detach() # Reintroduce gradients here. &lt;------------
x = self.linear2(x)

The answer is in the fifth line, by subtracting and then adding back again.  Gradients can then be reintroduced.