The way I would do this is the following (assuming there are NO learnable parameters in nondifferentiable_but_exact and differentiable_but_approximate_function and that you don’t need higher order gradients by using create_graph=True):
import torch


class Test(torch.autograd.Function):
    @staticmethod
    def forward(ctx, a, b):
        ctx.save_for_backward(a)
        exact_out = nondifferentiable_but_exact(a)
        return exact_out

    @staticmethod
    def backward(ctx, grad_output):
        a, = ctx.saved_tensors
        # Get new Tensor unrelated to a with same content
        local_a = a.detach().requires_grad_()
        with torch.enable_grad():
            approx_out = differentiable_but_approximate_function(a)
        grad = torch.autograd.grad(approx_out, local_a, grad_output)[0]
        return grad

a = torch.ones(1, requires_grad=True)

Test.apply(a).backward()