I encountered a similar situation when secure-wiping an external (USB 2.0) hard disk: long periods of reads followed by a few seconds of high throughput writes, when I expected 100% writes. I used pv to show me an overall write speed (see command below) and I was getting an average of 10MB/s, in bursts of 14MB/s for ~10 seconds followed by a few kB/s. My iostat output looked very much like yours.
It turned out that the issue was my much-too-small dd block size (512 bytes). I suspect that what's happening is that the kernel was reading blocks into its 1k-per-block buffers so that dd can overwrite 512 bytes at a time, which then got flushed. I'm not a kernel expert so that' just a guess.
I can say that pumping up my dd block size to 72K made a huge difference. I am now seeing >40MB/s sustained writes. This is pretty close to the theoretical maximum that USB 2.0 can provide (480Kb/s, not counting USB overhead) and also pretty close to the maximum sustained write speed that this 10 year old disk can achieve (something like 55MB/s), so I'm satisfied that this is more or less bare-metal speed.
Here's the command I'm using to wipe the drive:
openssl enc -aes-256-ctr -pass \
pass:"$(dd if=/dev/urandom bs=128 count=1 2>/dev/null | base64)" \
-nosalt </dev/zero \
| pv -bartpes 160041885696 -B 128K \
| dd bs=72K count=2170707 of=/dev/sdf iflag=fullblock
Lines 1-3 pipe /dev/zero through AES-256-CTR encryption, using a password generated from /dev/urandom. So it's a stream of cryptographically random garbage.
Line 4 shows progress, given the 160GB drive's byte count and using a transfer buffer size in pv of 128KiB.
Line 5 uses a block size that I picked using a calculator, trying to find the largest multiple of 512 that was a factor of the total # of bytes of the drive. iflag=fullblock makes dd read repeatedly into its buffer until it has 1 full block before writing.