Basically, all OCaml code runs in IO. You can still only modify things that you've marked as modifiable (analogous to an IORef), but there is no constraint on where you can modify them from.
(In case it's unclear, I'm agreeing with tel and rephrasing.)
One advantage that gives you, is that you can easily define a monad on top of that and not worry about monad transformers. Jane Streets async library does that in its Deferred module https://ocaml.janestreet.com/ocaml-core/111.17.00/doc/async/...
The ST monad lets you transition from regions which allow mutation to pure regions and then back again.