Thanks but this only acts as a one time initialization , its as if I write :
def __init__(self):
    super().__init__()
    self.conv1 = nn.Conv2d(3, 6, 3) 
    shape = self.conv1.weight.shape
    self.conv1.weight = nn.Parameter(torch.rand(shape)) + nn.Parameter(torch.rand(shape))

and use self.conv in the forward pass!
The difference is that here the values of the self.kernel will get optimized, but what I’m after is that I want the values of self.var1 and self.var2 to get changed so that their interactions result in a  set of filters/kernels ( the resulting weight matrix) that minimize the loss.
In other words, in your self.kernel case, there are n entries that get learned, but in my case, there are 2x more variables that are used to create  a kernel.
The method call is necessary since, each time its called in the forward pass, it runs the underlying operation that creates a new set of filters, then these filters are used, some losses will be produced and ultimately a set of gradients will be created, I want these gradients to update not the filters values themselves, but the self.var1 and self.var2 values that create the filters values