You should just take your original function and instead of giving it a Tensor as input, give it a Variable containing the Tensor.
This way, all operations will be made on the Variables and you will be able to backpropagate from the output.
 def Test(InputMatrix):
    D = len(InputMatrix)
    Grid_R = torch.zeros(D,D)
    for i in range(len(Grid_R)):
        Grid_R[i][:] = i
        
    DCT_Matrix = (torch.sin(Grid_R+0.05)*(Grid_R /D))
    print(DCT_Matrix)
    # Always package temporary elements into Variable when they are going to be
    # used with other elements for which you require gradients.
    DCT_Matrix_var = Variable(DCT_Matrix)
    DCT_Output = torch.mm(DCT_Matrix_var,torch.t(InputMatrix))
    return DCT_Output