You could unfold an image tensor, apply a convolution via a matrix multiplication, and fold it back to the desired output in order to e.g. write a custom conv (where you could add additional operations), for custom pooling layers etc.
Also, creating “windows” from e.g. time signals can use the same approach.