Wouldn’t my code snippet yield exactly this? 
Have a look at this comparison with a manual approach, where each kernel is used on a single input channel:
# Grouped approach
conv = nn.Conv2d(3, 3, 3, groups=3, bias=False)
x = torch.randn(10, 3, 64, 64)
output = conv(x)

# Compare with manual approach
kernels = conv.weight
output_manual = []
for idx in range(3):
    kernel = kernels[idx:idx+1]
    input = x[:, idx:idx+1]
    out = F.conv2d(input, kernel)
    output_manual.append(out)
output_manual = torch.cat(output_manual, dim=1)

print((output_manual - output).abs().max())
> tensor(4.7684e-07, grad_fn=<MaxBackward1>)

Let me know, if I still misunderstand the use case.