Update: I managed to avoid the segfault when calling zero_tensor in my module. The trick was to add an import torch to my python script!
Previously, my python script looked like this:
#!/usr/bin/python3
import dummy

dummy.zero_tensor(3,4,5)

(here, dummy is the name of my module). The above script causes a segfault. But when I modify it to be
#!/usr/bin/python3
import dummy
import torch

dummy.zero_tensor(3,4,5)

… it works.
Why this happens:
In torch/csrc/autograd/python_variable.cpp there is a variable called THPVariableClass, which is initialised to nullptr. The method THPVariable_Wrap (which we can see in the valgrind trace above) calls  THPVariable_NewWithVar with (PyTypeObject*)THPVariableClass as the type argument, which is still the null pointer. THPVariable_NewWithVar then tries to call type->tp_alloc(type, 0) (where type is the nullptr), causing the segmentation fault.
Normally, it seems THPVariableClass is supposed to be initialised by the function PyObject* THPAutograd_initExtension(PyObject* _unused, PyObject *unused) (inside torch/csrc/autograd/init.cpp) which, it turns out, is automatically called when you do import torch. So adding import torch fixed the problem.
Is this is a bug in pytorch? My guess would be that importing any custom pytorch/pybind C++ module should automatically cause torch to be imported too in order for this segfault not to happen. At the very least I would say that either THPVariable_Wrap or THPVariable_NewWithVar should check that THPVariableClass is initialised (not null) and, if not, throw an exception along with instructions on how the user can fix the issue.