(Note: This is the answer originally provided in the question body by the OP).
Problem solved. I needed to create an array of D3D11_SUBRESOURCE_DATA elements, one for each element in the Texture2DArray. Like this:
D3D11_TEXTURE2D_DESC sTexDesc;
sTexDesc.Width = m_uTextureWidth;
sTexDesc.Height = m_uTextureHeight;
sTexDesc.MipLevels = 1;
sTexDesc.ArraySize = 16;
sTexDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sTexDesc.SampleDesc.Count = 1;
sTexDesc.SampleDesc.Quality = 0;
sTexDesc.Usage = D3D11_USAGE_IMMUTABLE;
sTexDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
sTexDesc.CPUAccessFlags = 0;
sTexDesc.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA *sSubData = new D3D11_SUBRESOURCE_DATA[16];
for(int i=0; i<16; i++) {
sSubData[i].pSysMem = ubImageStorage;
sSubData[i].SysMemPitch = (UINT) (1024 * 4);
sSubData[i].SysMemSlicePitch = (UINT) (1024 * 1024 * 4);
}
ID3D11Texture2D* pTexture;
hr = m_pd3dDevice->CreateTexture2D(&sTexDesc,sSubData,&pTexture);
delete [] sSubData;
Note that I've replaced the variables in the code above with constants, but allocated the D3D11_SUBRESOURCE_DATA array dynamically because its size is unknown at compile time.
Why would you ever have different slices with different pitches? Is that even really supported? That seems really strange.