^SPOOL(docIdx) approach allows spooling sharing across ECP network, while ^SPOOL($j) does not :)

%IS is an utility which allows to choose devices by CHUI routines users and %SPOOL utility can manipulate with spool files opened using the %IS utility only.

It seems that initial purpose of spooling facility has gone with such a users and such a printers (strictly character based, w/o ability of font selection, etc), while its usage still can be actual in rather exotic cases like this one.

Yeah, but it should be used with precautions. Let's see what happens when two processes access spooling device concurrently: 

USER>f {q:'($zh\1#20)} k a o 2 f i=1:1:10 {s a(i)=i*100} u 2 zw a c 2 ; process #1
USER>s i="" f  {s i=$o(^SPOOL(1,i),1,line) q:i=""  w line} ; look inside ^SPOOL(1)...
a(1)=100
a(2)=200
a(3)=300
a(4)=400
a(5)=500
a(6)=600
a(7)=700
a(8)=800
a(9)=900
a(10)=1000
{66892,65205{11
USER>f {q:'($zh\1#20)} k a o 2 f i=1:1:10 {s a(i)=i} u 2 zw a c 2 ; process #2
USER>s i="" f  {s i=$o(^SPOOL(1,i),1,line) q:i=""  w line} ; look inside ^SPOOL(1)...
a(1)=100
a(2)=200
a(3)=300
a(4)=400
a(5)=500
a(6)=600
a(7)=700
a(8)=800
a(9)=900
a(10)=1000
{66892,65205{11

As you can notice, one process's output suppressed the other's one. To avoid it, firstly RTFM: OPEN and USE Commands for Spooling Device, and implement some synchronization pattern, e.g. 

USER>f {q:'($zh\1#20)} s docIdx=$i(^SPOOL) k a o 2:(docIdx) f i=1:1:10 {s a(i)=i*100} u 2 zw a c 2 ; process #1
USER>s i="" f  {s i=$o(^SPOOL(docIdx,i),1,line) q:i=""  w line}
a(1)=100
a(2)=200
a(3)=300
a(4)=400
a(5)=500
a(6)=600
a(7)=700
a(8)=800
a(9)=900
a(10)=1000
{66892,66645{11{
USER>f {q:'($zh\1#20)} s docIdx=$i(^SPOOL) k a o 2:(docIdx) f i=1:1:10 {s a(i)=i} u 2 zw a c 2 ; process #2
USER>s i="" f  {s i=$o(^SPOOL(docIdx,i),1,line) q:i=""  w line}
a(1)=1
a(2)=2
a(3)=3
a(4)=4
a(5)=5
a(6)=6
a(7)=7
a(8)=8
a(9)=9
a(10)=10
{66892,66645{11{

Each process has got it's own output in ^SPOOL(docIdx) now. This approach works if every consumer of spooling facility follows the same pattern; incrementing ^SPOOL is just an easiest approach, while it would be better avoid touching system globals and increment something else according to your taste.

I'd like to collect tables based on logs

In general, such approach is far from optimal for Caché like databases because logs (which are usually called  "journals" in Caché/M world) are being written on global (= lowest possible) level, disregard of data model used by an app (SQL, Persistent classes, etc). Reconstructing app level data from underlying globals can be a tricky task even for Caché guru.

That was one of the reasons why colleagues of mine took another approach for close to real-time data export from Caché to external system. In a few words, they used triggers to form application level data packets on Caché side and pipe them to the receiver. This approach saved CPU time preventing its waste for filtering out unnecessary journal records and minimized cross-system network traffic.

Robert, it sounds strange, but... Setting the Time Zone

You can use $ZTIMEZONE to set the time zone used by the current InterSystems IRIS process. Setting $ZTIMEZONE does not change the default InterSystems IRIS time zone or your computer’s time zone setting.

IMHO, $ztimezone setting is dangerous not for its system-wide effect (which it hasn't) but mostly due to its exclusions and anomalies, despite they are accurately listed in docs.

the first letter becomes the last letter, the second letter becomes the second-to-last letter, and so on

This definition means string reverse rather than rotation, while you apparently meant right (or clockwise) string rotation which is:
1st character becomes the 2nd, last ones becomes the 1st, repeat until the first string will become equal to the second string. As to your sample:
hello -> ohell -> lohel -> llohe